package com.mkl.ttxt.pd.util;

import com.alibaba.fastjson.JSON;
import com.mkl.ttxt.common.bo.TtxtResult;
import com.mkl.ttxt.common.constant.BaseConstant;
import com.mkl.ttxt.common.exception.BusinessException;
import com.mkl.ttxt.pd.bo.*;
import com.mkl.ttxt.pd.dao.IPdDao;
import io.netty.util.internal.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.*;

@Component
public class PlanUtilV2 {

    @Autowired
    private static IPdDao iPdDao;

    @Autowired
    private static BaseConstant baseConstant;

    private static List<Target> targetList;

    private static boolean excuteFlag = false;

    private static Integer lastMinBlood;
    private static Integer doneMemberNum = 0;
    private static List<String> doneMemberIdList = new ArrayList<>();
    private static List<Lineup> lineupList;
    private static List<Integer> notAvailableLineUpIdList = new ArrayList<>();
    private static List<LineupCompose> lineupComposeList = new ArrayList<>();

    @Autowired
    public PlanUtilV2(IPdDao iPdDao, BaseConstant baseConstant) {
        PlanUtilV2.iPdDao = iPdDao;
        PlanUtilV2.baseConstant = baseConstant;
    }

    public static void resetFlag(){
        PlanUtilV2.excuteFlag = false;
    }

    public static boolean getFlag(){
        return PlanUtilV2.excuteFlag;
    }

    public static TtxtResult planning(List<Target> targetList, Integer userId) throws Exception {
        if(excuteFlag){
            throw new BusinessException("正在自动排刀，请稍后");
        }
        //删除旧文件
        File oldFile = new File(userId + "resultFinal.csv");
        oldFile.delete();
        oldFile = new File(userId + "resultTemp.csv");
        oldFile.delete();

        PlanUtilV2.lineupList = iPdDao.getAllLineup(userId);
        //设置目标
        for(Target target: targetList){
            if(target.getRemainBlood() == null || target.getRemainBlood() ==0){
                target.setRemainBlood(target.getTotalBlood());
            }
            PlanUtilV2.lastMinBlood = target.getTotalBlood();
        }
        PlanUtilV2.targetList = targetList;
        excuteFlag = true;
        doneMemberNum = 0;
        doneMemberIdList = new ArrayList<>();
        lineupComposeList = new ArrayList<>();
        notAvailableLineUpIdList = new ArrayList<>();
        TtxtResult ttxtResult = null;
        try{
            ttxtResult = excute(userId);
        }catch (Exception e){
            e.printStackTrace();
            excuteFlag = false;
            throw e;
        }
        excuteFlag = false;
        return ttxtResult;
    }

    private static TtxtResult excute(Integer userId) throws IOException {
        //计算剩余血量最多的BOSS
        TtxtResult ttxtResult = new TtxtResult(BaseConstant.SUCCESS);
        Integer bossNo = getMaxBoss();
        if(doneMemberNum >= 28){
            System.out.println("临时记录");
            recordResult("Temp", userId);
        }
        if(doneMemberNum >= 30){
            System.out.println("30人排刀完毕");
            recordResult("Final", userId);
            return ttxtResult;
        }
        if(bossNo == null || bossNo == 0){
            System.out.println("boss已处理完");
            recordResult("Final", userId);
            return ttxtResult;
        }
        //获取评分最高，且能打血最多的BOSS的组合
        List<Integer> lineupIdList = iPdDao.getLineupIdListByBossNo(userId, bossNo);
        if(lineupIdList == null || lineupIdList.size() < 1){
            throw new BusinessException("阵容不完整，不能打这个BOSS:" + bossNo);
        }
        List<Integer> availableLineUpIdList = getAvailableLineUpIdList(userId);
        LineupCompose bestCompose = iPdDao.getBestCompose(userId, lineupIdList, availableLineUpIdList);

        if(bestCompose == null){
            System.out.println("不能继续出刀,补充阵容,可下载临时文件");
            recordResult("Temp", userId);
            ttxtResult.setCode(1);
            ttxtResult.setMessage("不能继续出刀,补充阵容,可下载临时文件");
            return ttxtResult;
        }
        //获取能出这个组合，且可选组合 最少 的人，出到有一个BOSS血量到血线以下
        List<String> memberIdList = new ArrayList<>(Arrays.asList(bestCompose.getMemberIds().split(",")));
        memberIdList.removeAll(doneMemberIdList);
        while(memberIdList == null || memberIdList.size() == 0){
            //最优阵容没人能出了，去安排剩下的人
            notAvailableLineUpIdList.add(bestCompose.getId());
            bestCompose = iPdDao.getSecondCompose(userId, lineupIdList, availableLineUpIdList, notAvailableLineUpIdList);
            if(bestCompose == null){
                System.out.println("不能继续出刀,补充阵容,可下载临时文件");
                recordResult("Temp", userId);
                ttxtResult.setCode(1);
                ttxtResult.setMessage("不能继续出刀,补充阵容,可下载临时文件");
                return ttxtResult;
            }
            memberIdList = new ArrayList<>(Arrays.asList(bestCompose.getMemberIds().split(",")));
            memberIdList.removeAll(doneMemberIdList);
        }
        //最少组合人从低到高排序
        List<Integer> memberIdOrderList = iPdDao.orderLineupMember(memberIdList, userId);

        for(Integer memberId: memberIdOrderList){
            LineupCompose tempLineupCompose = new LineupCompose();
            tempLineupCompose.setMemberId(memberId);
            tempLineupCompose.setMemberIds(null);
            tempLineupCompose.setId(bestCompose.getId());
            tempLineupCompose.setLineup1(bestCompose.getLineup1());
            tempLineupCompose.setLineup2(bestCompose.getLineup2());
            tempLineupCompose.setLineup3(bestCompose.getLineup3());
            tempLineupCompose.setScore(bestCompose.getScore());
            tempLineupCompose.setLineup1Detail(getLineup(bestCompose.getLineup1()));
            tempLineupCompose.setLineup2Detail(getLineup(bestCompose.getLineup2()));
            tempLineupCompose.setLineup3Detail(getLineup(bestCompose.getLineup3()));
            if(!checkLineupCompose(tempLineupCompose)) {
                break;
            }else{
                doneMemberNum++;
                excuteLinueupCompose(tempLineupCompose, doneMemberNum);
                doneMemberIdList.add(String.valueOf(memberId));
            }
        }
        return excute(userId);
    }

    private static List<Integer> getAvailableLineUpIdList(Integer userId) throws IOException {
        Map<Integer, Integer> bossMap = new HashMap<>();
        for(Target target:PlanUtilV2.targetList){
            if(bossMap.containsKey(target.getBossNo())){
                bossMap.put(target.getBossNo(), bossMap.get(target.getBossNo()) + target.getRemainBlood());
            }else{
                bossMap.put(target.getBossNo(), target.getRemainBlood());
            }
        }
        List<Integer> todoBossNoList = new ArrayList<>();
        Integer maxRemainBlood = baseConstant.BLOOD_LINE;
        for(Integer bossNo: bossMap.keySet()){
            if(bossMap.get(bossNo) > maxRemainBlood){
                todoBossNoList.add(bossNo);
            }
        }
        if(todoBossNoList == null || todoBossNoList.size() == 0){
            recordResult("Temp", userId);
            System.out.println("只剩最后一个BOSS");
            return null;
        }
        List<Integer> availableLineUpIdList = iPdDao.getLineupIdListByBossNoList(userId, todoBossNoList);
        return availableLineUpIdList;
    }

    private static Integer getMaxBoss() {
        Map<Integer, Integer> bossMap = new HashMap<>();
        for(Target target:PlanUtilV2.targetList){
            if(bossMap.containsKey(target.getBossNo())){
                bossMap.put(target.getBossNo(), bossMap.get(target.getBossNo()) + target.getRemainBlood());
            }else{
                bossMap.put(target.getBossNo(), target.getRemainBlood());
            }
        }
        Integer maxBossNo = 0;
        Integer maxRemainBlood = baseConstant.BLOOD_LINE;
        for(Integer bossNo: bossMap.keySet()){
            if(bossMap.get(bossNo) > maxRemainBlood){
                maxRemainBlood = bossMap.get(bossNo);
                maxBossNo = bossNo;
            }
        }
        return maxBossNo;
    }

    private static void recordResult(String state, Integer userId) throws IOException {
        String content = getResultContent();
        File file = new File(userId + "result" + state + ".csv");
        if(!file.exists()){
            file.createNewFile();
        }
        FileWriter fileWritter = new FileWriter(file.getName(),true);
        fileWritter.write(content);
        fileWritter.close();
    }

//    private static String getResultContent() {
//        String result = "BOSS状态：\r\n";
//        for(Target target: PlanUtilV2.targetList){
//            result += target.getBossNo() + "王目标：" + target.getTotalBlood() + "万，剩余:" + target.getRemainBlood() + "万\r\n";
//        }
//        result += "排刀结果:\r\n";
//        Integer totalScore = 0;
//        for(LineupCompose lineupCompose: PlanUtilV2.lineupComposeList){
//            lineupCompose.setLineup1Detail(getLineupDetail(lineupCompose.getLineup1Detail()));
//            lineupCompose.setLineup2Detail(getLineupDetail(lineupCompose.getLineup2Detail()));
//            lineupCompose.setLineup3Detail(getLineupDetail(lineupCompose.getLineup3Detail()));
//            lineupCompose.setMemberNames(iPdDao.getMembersByIds(new ArrayList<String>(Arrays.asList(String.valueOf(lineupCompose.getMemberId())))));
//
//            result += lineupCompose.getMemberNames() + "|";
//            result += lineupCompose.getLineup1Detail().getBossNo() + "王|" +
//                    lineupCompose.getLineup1Detail().getDamage() + "|";
//            for(LineupCard lineupCard: lineupCompose.getLineup1Detail().getLineupCardList()){
//                result += lineupCard.getStar() + "星" + lineupCard.getCardName() + "/" ;
//            }
//            result += "|";
//            result += lineupCompose.getLineup2Detail().getBossNo() + "王|" +
//                    lineupCompose.getLineup2Detail().getDamage() + "|";
//            for(LineupCard lineupCard: lineupCompose.getLineup2Detail().getLineupCardList()){
//                result += lineupCard.getStar() + "星" + lineupCard.getCardName() + "/";
//            }
//            result += "|";
//            result += lineupCompose.getLineup3Detail().getBossNo() + "王|" +
//                    lineupCompose.getLineup3Detail().getDamage() + "|";
//            for(LineupCard lineupCard: lineupCompose.getLineup3Detail().getLineupCardList()){
//                result += lineupCard.getStar() + "星" + lineupCard.getCardName() + "/";
//            }
//            result += "\r\n";
//            totalScore += lineupCompose.getScore();
//        }
//        result += "总分：" + totalScore + "\r\n";
//        result += "----------------------------------------------------------------------------------------\r\n";
//        return result;
//    }

    private static String getResultContent() {
        String result = "BOSS状态：\r\n";
        for(Target target: PlanUtilV2.targetList){
            result += target.getBossNo() + "王目标：" + target.getTotalBlood() + "万，剩余:" + target.getRemainBlood() + "万\r\n";
        }
        result += "排刀结果:\r\n";
        Integer totalScore = 0;
        for(LineupCompose lineupCompose: PlanUtilV2.lineupComposeList){
            lineupCompose.setLineup1Detail(getLineupDetail(lineupCompose.getLineup1Detail()));
            lineupCompose.setLineup2Detail(getLineupDetail(lineupCompose.getLineup2Detail()));
            lineupCompose.setLineup3Detail(getLineupDetail(lineupCompose.getLineup3Detail()));
            lineupCompose.setMemberNames(iPdDao.getMembersByIds(new ArrayList<String>(Arrays.asList(String.valueOf(lineupCompose.getMemberId())))));

            result += lineupCompose.getMemberNames() + ",";
            result += lineupCompose.getLineup1Detail().getBossNo() + "王" +
                    lineupCompose.getLineup1Detail().getDamage() + "w,";
            result += lineupCompose.getLineup1Detail().getRemark() ;

            result += ",";
            result += lineupCompose.getLineup2Detail().getBossNo() + "王" +
                    lineupCompose.getLineup2Detail().getDamage() + "w,";
            result += lineupCompose.getLineup2Detail().getRemark() ;

            result += ",";
            result += lineupCompose.getLineup3Detail().getBossNo() + "王" +
                    lineupCompose.getLineup3Detail().getDamage() + "w,";
            result += lineupCompose.getLineup3Detail().getRemark() ;

            result += "\r\n";
            totalScore += lineupCompose.getScore();
        }
        result += "总分：" + totalScore + "\r\n";
        result += "----------------------------------------------------------------------------------------\r\n";
        return result;
    }

    private static Lineup getLineupDetail(Lineup lineup) {
        List<LineupCard> cardList = JSON.parseArray(lineup.getLineup(), LineupCard.class);
        if(cardList == null || cardList.size() < 1){
            lineup.setLineup(null);
            return lineup;
        }
        for (LineupCard card : cardList) {
            card.setCardName(iPdDao.getCardName(card.getCardId()));
        }
        lineup.setLineup(null);
        lineup.setLineupCardList(cardList);
        return lineup;
    }

    private static Lineup getLineup(Integer lineup1) {
        for(Lineup lineup :PlanUtilV2.lineupList){
            if(lineup.getId().equals(lineup1)){
                return lineup;
            }
        }
        return null;
    }

    //判断这刀能不能出
    private static boolean checkLineupCompose(LineupCompose lineupCompose) {
        //检查BOSS血够不够
        Lineup lineup1 = lineupCompose.getLineup1Detail();
        boolean lineup1Flag = false;
        Lineup lineup2 = lineupCompose.getLineup2Detail();
        boolean lineup2Flag = false;
        Lineup lineup3 = lineupCompose.getLineup3Detail();
        boolean lineup3Flag = false;
        boolean result = false;
        boolean bossAllDown = true;
        for(Target target: PlanUtilV2.targetList){
            if(target.getRemainBlood() > baseConstant.BLOOD_LINE){
                bossAllDown = false;
            }
            if(!lineup1Flag && target.getBossNo().equals(lineup1.getBossNo())){
                if(target.getRemainBlood() > baseConstant.BLOOD_LINE){
                    lineup1Flag = true;
                    continue;
                }
            }
            if(!lineup2Flag && target.getBossNo().equals(lineup2.getBossNo())){
                if(target.getRemainBlood() > baseConstant.BLOOD_LINE){
                    lineup2Flag = true;
                    continue;
                }
            }
            if(!lineup3Flag && target.getBossNo().equals(lineup3.getBossNo())){
                if(target.getRemainBlood() > baseConstant.BLOOD_LINE){
                    lineup3Flag = true;
                    continue;
                }
            }
        }
        if(!lineup1Flag && !lineup2Flag && !lineup3Flag){
            result = false;
        }

        if(lineup1Flag && lineup2Flag && lineup3Flag){
            result = true;
        }
        if(bossAllDown){
            throw new BusinessException("BOSS血量不足，请重新设定目标");
        }
        return result;
    }

    //出这刀
    private static void excuteLinueupCompose(LineupCompose lineupCompose, int i){
        //扣BOSS血
        Lineup lineup1 = lineupCompose.getLineup1Detail();
        boolean lineup1Flag = false;
        Lineup lineup2 = lineupCompose.getLineup2Detail();
        boolean lineup2Flag = false;
        Lineup lineup3 = lineupCompose.getLineup3Detail();
        boolean lineup3Flag = false;
        for(Target target: PlanUtilV2.targetList){
            if(!lineup1Flag && target.getBossNo().equals(lineup1.getBossNo())
                    && (target.getRemainBlood() > baseConstant.BLOOD_LINE)
            ){
                target.setRemainBlood(target.getRemainBlood() - lineup1.getDamage());
                lineup1Flag = true;
                continue;
            }
            if(!lineup2Flag && target.getBossNo().equals(lineup2.getBossNo())
                    && (target.getRemainBlood() > baseConstant.BLOOD_LINE)
            ){
                target.setRemainBlood(target.getRemainBlood() - lineup2.getDamage());
                lineup2Flag = true;
                continue;
            }
            if(!lineup3Flag && target.getBossNo().equals(lineup3.getBossNo())
                    && (target.getRemainBlood() > baseConstant.BLOOD_LINE)
            ){
                target.setRemainBlood(target.getRemainBlood() - lineup3.getDamage());
                lineup3Flag = true;
                continue;
            }
        }
        if(!lineup1Flag || !lineup2Flag || !lineup3Flag){
            throw new BusinessException("出刀失败");
        }
        //记录这一刀
        PlanUtilV2.lineupComposeList.add(lineupCompose);

    }
}
